package com.ccb.sc.member.service;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ccb.sc.member.vo.DailyTaskVo;
import com.ccb.sc.common.modules.common.service.IRedisService;
import com.ccb.sc.common.modules.member.entity.MemberPointsLog;
import com.ccb.sc.common.modules.member.enums.MemberPointsLogType;
import com.ccb.sc.common.modules.member.service.MemberPointsService;
import com.ccb.sc.common.modules.message.enums.MessageType;
import com.ccb.sc.common.modules.message.service.MessageService;
import com.ccb.sc.common.modules.setting.service.ISettingsService;
import com.ccb.sc.common.modules.setting.vo.DailyTaskPointRuleSettingsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author ken
 * @version 1.0
 * @date 2022/8/18 22:53
 */
@Service
public class DailyTaskService {

    @Autowired
    private ISettingsService settingsService;

    @Autowired
    private SignInService signInService;

    @Autowired
    private MemberPointsService memberPointsService;

    @Autowired
    private IRedisService redisService;

    @Autowired
    private MessageService messageService;

    public List<DailyTaskVo> findDailyTasks(Long memberId) {
        List<DailyTaskVo> tasks = new ArrayList<>();
        DailyTaskPointRuleSettingsVo settings = this.settingsService.getSettings(DailyTaskPointRuleSettingsVo.class);
        if (settings == null) {
            return tasks;
        }
        LocalDate now = LocalDate.now();
        List<MemberPointsLog> memberPointsLogs = this.memberPointsService.list(Wrappers.<MemberPointsLog>lambdaQuery()
                .eq(MemberPointsLog::getMemberId, memberId)
                .between(MemberPointsLog::getCreateTime, now, now.plusDays(1)));
        Set<MemberPointsLogType> logSet = new HashSet<>();
        if (!CollectionUtils.isEmpty(memberPointsLogs)) {
            logSet = memberPointsLogs.stream().map(MemberPointsLog::getChangeType).collect(Collectors.toSet());
        }

        if (settings.getSignIn() > 0) {
            DailyTaskVo signInTask = new DailyTaskVo();
            signInTask.setType(MemberPointsLogType.SIGN_IN.getDesc());
            signInTask.setAward(settings.getSignIn());
            signInTask.setDone(logSet.contains(MemberPointsLogType.SIGN_IN));
            tasks.add(signInTask);
        }
        if (settings.getShare() > 0) {
            DailyTaskVo shareTask = new DailyTaskVo();
            shareTask.setType(MemberPointsLogType.SHARE.getDesc());
            shareTask.setAward(settings.getShare());
            shareTask.setDone(logSet.contains(MemberPointsLogType.SHARE));
            tasks.add(shareTask);
        }
        if (settings.getLivePreview() > 0) {
            DailyTaskVo livePreviewTask = new DailyTaskVo();
            livePreviewTask.setType(MemberPointsLogType.LIVE_PREVIEW.getDesc());
            livePreviewTask.setAward(settings.getLivePreview());
            livePreviewTask.setDone(logSet.contains(MemberPointsLogType.LIVE_PREVIEW));
            tasks.add(livePreviewTask);
        }
        if (settings.getRaidersDocument() > 0) {
            DailyTaskVo livePreviewTask = new DailyTaskVo();
            livePreviewTask.setType(MemberPointsLogType.RAIDERS_DOCUMENT.getDesc());
            livePreviewTask.setAward(settings.getRaidersDocument());
            livePreviewTask.setDone(logSet.contains(MemberPointsLogType.RAIDERS_DOCUMENT));
            tasks.add(livePreviewTask);
        }
        if (settings.getVisitGoodsReward() > 0) {
            DailyTaskVo reserveTask = new DailyTaskVo();
            reserveTask.setType(MemberPointsLogType.RESERVE.getDesc());
            reserveTask.setAward(settings.getVisitGoodsReward());
            reserveTask.setDone(logSet.contains(MemberPointsLogType.RESERVE));
            tasks.add(reserveTask);
        }
        if (settings.getJoinGroup() > 0) {
            DailyTaskVo joinGroupTask = new DailyTaskVo();
            joinGroupTask.setType(MemberPointsLogType.JOIN_GROUP.getDesc());
            joinGroupTask.setAward(settings.getJoinGroup());
            boolean hasJoinGroup = this.memberPointsService.count(Wrappers.<MemberPointsLog>lambdaQuery()
                    .eq(MemberPointsLog::getMemberId, memberId)
                    .eq(MemberPointsLog::getChangeType, MemberPointsLogType.JOIN_GROUP)) > 0;
            joinGroupTask.setDone(hasJoinGroup);
            tasks.add(joinGroupTask);
        }
        return tasks;
    }

    public int reward(Long memberId, MemberPointsLogType logType, String associate) {
        String redisKey = String.format("lock:award:%s:%s", logType.getValue(), memberId);
        String randomStr = UUID.randomUUID().toString();
        int reward = 0;
        try {
            boolean lock = this.redisService.lock(redisKey, randomStr, 5);
            if (!lock) {
                return reward;
            }
            DailyTaskPointRuleSettingsVo settings = this.settingsService.getSettings(DailyTaskPointRuleSettingsVo.class);
            if (settings == null) {
                return reward;
            }
            String messageBody = "";
            if (MemberPointsLogType.JOIN_GROUP.equals(logType)) {
                reward = settings.getJoinGroup();
                boolean hasJoinGroup = this.memberPointsService.count(Wrappers.<MemberPointsLog>lambdaQuery()
                        .eq(MemberPointsLog::getMemberId, memberId)
                        .eq(MemberPointsLog::getChangeType, MemberPointsLogType.JOIN_GROUP)) > 0;
                if (hasJoinGroup) {
                    return 0;
                }
                messageBody = String.format("恭喜您通过加入会员群获得%d积分", reward);
            }else {
                if (MemberPointsLogType.SHARE.equals(logType)) {
                    reward = settings.getShare();
                    messageBody = String.format("恭喜您通过分享获得%d积分", reward);
                }else if (MemberPointsLogType.LIVE_PREVIEW.equals(logType)) {
                    reward = settings.getLivePreview();
                    messageBody = String.format("恭喜您通过观看直播预告获得%d积分", reward);
                }else if (MemberPointsLogType.RAIDERS_DOCUMENT.equals(logType)) {
                    reward = settings.getRaidersDocument();
                    messageBody = String.format("恭喜您通过浏览攻略文档获得%d积分", reward);
                }else if (MemberPointsLogType.RESERVE.equals(logType)) {
                    reward = settings.getVisitGoodsReward();
                    messageBody = String.format("恭喜您通过预约直播商品获得%d积分", reward);
                }else {
                    return 0;
                }
                boolean done = this.memberPointsService.isDone(memberId, logType);
                if (done) {
                    return 0;
                }
            }
            if (reward <= 0) {
                return 0;
            }
            this.memberPointsService.award(memberId, reward, logType, associate);

            this.messageService.create(memberId, MessageType.POINTS, MessageType.POINTS.getDesc(), messageBody);
        }finally {
            boolean unLock = this.redisService.unLock(redisKey, randomStr);
            if (!unLock) {
                this.redisService.unLock(redisKey, randomStr);
            }
        }
        return reward;
    }
}
